/**
 * @file Ajax 请求模块
 * @description 封装 HTTP 请求，支持拦截器、超时、重试等功能
 * @author Fieldano Team
 * @创建时间 2025-10-30
 */

import axios, {
  type AxiosError,
  type AxiosInstance,
  type AxiosRequestConfig,
  type AxiosResponse,
  type InternalAxiosRequestConfig
} from 'axios'

/**
 * 请求配置接口
 */
export interface RequestConfig extends AxiosRequestConfig {
  /** 是否显示加载提示 */
  showLoading?: boolean
  /** 是否显示错误提示 */
  showError?: boolean
  /** 重试次数 */
  retry?: number
  /** 重试延迟（毫秒） */
  retryDelay?: number
  /** 自定义错误处理 */
  customErrorHandler?: (error: any) => void
}

/**
 * 响应数据接口（根据实际后端 API 调整）
 */
export interface ApiResponse<T = any> {
  code: number
  msg: string
  data: T
}

/**
 * Ajax 请求类
 */
class Ajax {
  private instance: AxiosInstance
  private loadingCount = 0
  private defaultConfig: RequestConfig = {
    timeout: 30_000,
    showLoading: false,
    showError: true,
    retry: 0,
    retryDelay: 1000
  }

  constructor(config?: RequestConfig) {
    console.log('import.meta.env:', import.meta.env.VITE_API_BASE_URL)
    // 创建 axios 实例
    this.instance = axios.create({
      baseURL: import.meta.env.VITE_API_BASE_URL || process.env.VITE_API_BASE_URL || '',
      timeout: config?.timeout || this.defaultConfig.timeout,
      headers: {
        'Content-Type': 'application/json'
      },
      ...config
    })

    // 设置拦截器
    this.setupInterceptors()
  }

  /**
   * 设置请求和响应拦截器
   */
  private setupInterceptors(): void {
    // 请求拦截器
    this.instance.interceptors.request.use(
      (config: InternalAxiosRequestConfig) => {
        // 显示加载提示
        const customConfig = config as InternalAxiosRequestConfig & RequestConfig
        if (customConfig.showLoading) {
          this.showLoading()
        }

        // 添加认证 token（如果存在）
        const token = this.getToken()
        if (token && config.headers) {
          config.headers.Authorization = `Bearer ${token}`
        }

        // 添加时间戳防止缓存（GET 请求）
        if (config.method?.toLowerCase() === 'get') {
          config.params = {
            ...config.params,
            _t: Date.now()
          }
        }

        console.log(`[Ajax] 请求: ${config.method?.toUpperCase()} ${config.url}`, config)
        return config
      },
      (error: AxiosError) => {
        this.hideLoading()
        console.error('[Ajax] 请求错误:', error)
        return Promise.reject(error)
      }
    )

    // 响应拦截器
    this.instance.interceptors.response.use(
      (response: AxiosResponse) => {
        this.hideLoading()
        console.log(`[Ajax] 响应: ${response.config.url}`, response.data)

        // 根据实际后端 API 调整响应处理逻辑
        const { data } = response

        // 如果后端返回的是标准格式 { code, message, data }
        if (data && typeof data === 'object' && 'code' in data) {
          // 成功响应
          if (data.code === 200 || data.code === 0 || data.success === true) {
            return response
          }

          // 业务错误
          const error = new Error(data.message || '请求失败') as any
          error.response = response
          error.code = data.code

          // 显示错误提示
          const customConfig = response.config as RequestConfig
          if (customConfig.showError) {
            this.showError(data.message || '请求失败')
          }

          return Promise.reject(error)
        }

        // 直接返回数据
        return response
      },
      async (error: AxiosError) => {
        this.hideLoading()
        console.error('[Ajax] 响应错误:', error)

        const config = error.config as RequestConfig

        // 重试逻辑
        if (config && config.retry && config.retry > 0) {
          config.retry--
          console.log(`[Ajax] 重试请求 (剩余 ${config.retry} 次): ${config.url}`)

          await this.delay(config.retryDelay || this.defaultConfig.retryDelay!)
          return this.instance.request(config)
        }

        // 自定义错误处理
        if (config?.customErrorHandler) {
          config.customErrorHandler(error)
          throw error
        }

        // 默认错误处理
        const errorMessage = this.handleError(error)

        if (config?.showError) {
          this.showError(errorMessage)
        }

        throw error
      }
    )
  }

  /**
   * 处理错误信息
   */
  private handleError(error: AxiosError): string {
    if (error.response) {
      const { status, data } = error.response

      // HTTP 状态码错误
      switch (status) {
        case 400: {
          return (data as any)?.message || '请求参数错误'
        }
        case 401: {
          this.handleUnauthorized()
          return '未授权，请重新登录'
        }
        case 403: {
          return '拒绝访问'
        }
        case 404: {
          return '请求的资源不存在'
        }
        case 500: {
          return '服务器内部错误'
        }
        case 502: {
          return '网关错误'
        }
        case 503: {
          return '服务不可用'
        }
        case 504: {
          return '网关超时'
        }
        default: {
          return (data as any)?.message || `请求失败 (${status})`
        }
      }
    } else if (error.request) {
      // 请求已发送但没有收到响应
      if (error.code === 'ECONNABORTED') {
        return '请求超时，请稍后重试'
      }
      return '网络连接失败，请检查网络'
    } else {
      // 请求配置错误
      return error.message || '请求失败'
    }
  }

  /**
   * 处理未授权（401）
   */
  private handleUnauthorized(): void {
    // 清除 token
    this.clearToken()

    // 可以在这里触发登出逻辑或跳转到登录页
    console.warn('[Ajax] 未授权，已清除 token')

    // 如果需要跳转到登录页，可以使用路由
    // window.location.href = '/login'
  }

  /**
   * 获取 token
   */
  private getToken(): string | null {
    // 从 localStorage 或其他存储中获取 token
    return localStorage.getItem('auth_token')
  }

  /**
   * 清除 token
   */
  private clearToken(): void {
    localStorage.removeItem('auth_token')
  }

  /**
   * 显示加载提示
   */
  private showLoading(): void {
    this.loadingCount++
    // 可以在这里集成 UI 加载组件
    console.log('[Ajax] 显示加载提示')
  }

  /**
   * 隐藏加载提示
   */
  private hideLoading(): void {
    this.loadingCount--
    if (this.loadingCount <= 0) {
      this.loadingCount = 0
      // 可以在这里隐藏 UI 加载组件
      console.log('[Ajax] 隐藏加载提示')
    }
  }

  /**
   * 显示错误提示
   */
  private showError(message: string): void {
    // 可以在这里集成 UI 错误提示组件（如 Vuetify 的 snackbar）
    console.error('[Ajax] 错误:', message)

    // 示例：使用浏览器原生提示（实际项目中应该使用 UI 组件）
    // alert(message)
  }

  /**
   * 延迟函数
   */
  private delay(ms: number): Promise<void> {
    return new Promise(resolve => setTimeout(resolve, ms))
  }

  /**
   * GET 请求
   */
  get<T = any>(url: string, config?: RequestConfig): Promise<AxiosResponse<ApiResponse<T>>> {
    return this.instance.get(url, config)
  }

  /**
   * POST 请求
   */
  post<T = any>(
    url: string,
    data?: any,
    config?: RequestConfig
  ): Promise<AxiosResponse<ApiResponse<T>>> {
    return this.instance.post(url, data, config)
  }

  /**
   * PUT 请求
   */
  put<T = any>(
    url: string,
    data?: any,
    config?: RequestConfig
  ): Promise<AxiosResponse<ApiResponse<T>>> {
    return this.instance.put(url, data, config)
  }

  /**
   * DELETE 请求
   */
  delete<T = any>(url: string, config?: RequestConfig): Promise<AxiosResponse<ApiResponse<T>>> {
    return this.instance.delete(url, config)
  }

  /**
   * PATCH 请求
   */
  patch<T = any>(
    url: string,
    data?: any,
    config?: RequestConfig
  ): Promise<AxiosResponse<ApiResponse<T>>> {
    return this.instance.patch(url, data, config)
  }

  /**
   * 通用请求方法
   */
  request<T = any>(config: RequestConfig): Promise<AxiosResponse<ApiResponse<T>>> {
    return this.instance.request(config)
  }

  /**
   * 获取 axios 实例（用于高级用法）
   */
  getInstance(): AxiosInstance {
    return this.instance
  }

  // ==================== 简化数据提取方法 ====================

  /**
   * GET 请求（直接返回数据）
   * @description 自动提取 response.data.data，使用更简洁
   * @template T 数据类型
   * @param url 请求 URL
   * @param config 请求配置
   * @returns Promise<T> 直接返回数据
   *
   * @example
   * ```typescript
   * // 原始方式
   * const response = await ajax.get<User[]>('/api/users')
   * const users = response.data.data
   *
   * // 简化方式
   * const users = await ajax.getData<User[]>('/api/users')
   * ```
   */
  async getData<T = any>(url: string, config?: RequestConfig): Promise<T> {
    const response = await this.get<T>(url, config)
    return response.data.data
  }

  /**
   * POST 请求（直接返回数据）
   * @description 自动提取 response.data.data，使用更简洁
   * @template T 数据类型
   * @param url 请求 URL
   * @param data 请求数据
   * @param config 请求配置
   * @returns Promise<T> 直接返回数据
   *
   * @example
   * ```typescript
   * // 原始方式
   * const response = await ajax.post<User>('/api/users', userData)
   * const user = response.data.data
   *
   * // 简化方式
   * const user = await ajax.postData<User>('/api/users', userData)
   * ```
   */
  async postData<T = any>(url: string, data?: any, config?: RequestConfig): Promise<T> {
    const response = await this.post<T>(url, data, config)
    return response.data.data
  }

  /**
   * PUT 请求（直接返回数据）
   * @description 自动提取 response.data.data，使用更简洁
   */
  async putData<T = any>(url: string, data?: any, config?: RequestConfig): Promise<T> {
    const response = await this.put<T>(url, data, config)
    return response.data.data
  }

  /**
   * DELETE 请求（直接返回数据）
   * @description 自动提取 response.data.data，使用更简洁
   */
  async deleteData<T = any>(url: string, config?: RequestConfig): Promise<T> {
    const response = await this.delete<T>(url, config)
    return response.data.data
  }

  /**
   * PATCH 请求（直接返回数据）
   * @description 自动提取 response.data.data，使用更简洁
   */
  async patchData<T = any>(url: string, data?: any, config?: RequestConfig): Promise<T> {
    const response = await this.patch<T>(url, data, config)
    return response.data.data
  }

  /**
   * 通用请求方法（直接返回数据）
   * @description 自动提取 response.data.data，使用更简洁
   */
  async requestData<T = any>(config: RequestConfig): Promise<T> {
    const response = await this.request<T>(config)
    return response.data.data
  }
}

// 创建默认实例
export const ajax = new Ajax()

// 导出类以便创建自定义实例
export default Ajax

// 导出辅助函数
export * from './helpers'
